/* Copyright ©, 2022, ECARX (Hubei) Technology Co., Ltd. All rights reserved.
 *
 * NOTICE: This file contains information which is confidential and proprietary to ECARX
 * (Hubei) Technology Co., Ltd. and/or other developers. No license to any intellectual
 * property rights contained within this file is either granted or implied except as may be
 * provided in an agreement with ECARX (Hubei) Technology Co., Ltd.
 *
 * Any unauthorized copying or distribution of content from this file in whole or in part
 * is prohibited.
 */
#include "Dispatcher.h"

#include <algorithm>
#include <unordered_set>

using namespace ecarx::vhal::core;

namespace ecarx::vhal::core::notconfig {
extern std::map<int64_t, bool> notAvailables;
}

static int64_t token=0;
namespace ecarx::vhal::core {
Dispatcher::Dispatcher(const std::vector<int32_t>& signals)
    : changedSignal(signals) {
    std::sort(changedSignal.begin(), changedSignal.end());
    token++;
    if(token == 100){
        token = 1;
    }
    mToken = token;
}

bool Dispatcher::isExistChangedSignal(property::Area* area) {
    for (auto signal : area->getOwnSignals()) {
        if (std::binary_search(changedSignal.begin(), changedSignal.end(), signal)) {
            return true;
        }
    }
    return false;
}

void Dispatcher::dispatchSignal(impl::VendorVehicleServer* server, property::Area* area,
                                int32_t signalId, int64_t timestamp) {
    if (area->hasDependent()) {
        for (auto& property : area->getDependentProperties()) {
            //获取这个依赖的Area先执行
            auto propertyPtr = server->getProperty(property.prop);
            if (propertyPtr == nullptr) continue;
            property::Area* dependent = propertyPtr->getArea(property.area);
            if (isExistChangedSignal(dependent)) {
                dispatchSignal(server, dependent, signalId, timestamp);
            }
        }
    }
    auto status = area->exeSignalChanged(signalId, mToken, timestamp);
    int32_t propertyId = area->getIProperty()->getPropertyId();
    int32_t areaId = area->getAreaId();
    int64_t key = ((int64_t)areaId << 32) | propertyId;
    if (status == PropertyStatus::NotAvailable) {
        notconfig::notAvailables.insert_or_assign(key, true);
    } else {
        notconfig::notAvailables.erase(key);
    }
}
}  // namespace ecarx::vhal::core
